#ifndef UTILS_H_INCLUDED
#define UTILS_H_INCLUDED

#include <string>
#include <vector>

class CPair
{
public:
    CPair() : X(0), Y(0) { }
    CPair(int x, int y) : X(x), Y(y) { }

    int x() { return X; }
    int y() { return Y; }

    bool operator == (CPair other) { return (X == other.X && Y == other.Y); }
    bool operator != (CPair other) { return (X != other.X || Y != other.Y); }
    bool operator >= (CPair other) { return (X >= other.X && Y >= other.Y); }
    bool operator <= (CPair other) { return (X <= other.X && Y <= other.Y); }

    bool operator < (const CPair& other) const { return (X < other.X && Y < other.Y); }

    CPair operator + (int other) { return CPair(X + other, Y + other); }
    CPair operator - (int other) { return CPair(X - other, Y - other); }
    CPair operator + (CPair other) { return CPair(X + other.X, Y + other.Y); }
    CPair operator - (CPair other) { return CPair(X - other.X, Y - other.Y); }
    CPair& operator += (CPair other) { X += other.X; Y += other.Y; return *this; }
    CPair& operator -= (CPair other) { X -= other.X; Y -= other.Y; return *this; }

protected:
    int X, Y;
};

typedef CPair pair;

class CRect
{
public:
    CRect() : UpperLeft(0, 0), LowerRight(0, 0) {}
    CRect(pair upperLeft, pair lowerRight) : UpperLeft(upperLeft), LowerRight(lowerRight) {}
    CRect(int X, int Y, int W, int H) : UpperLeft(X, Y), LowerRight(X+W, Y+H) { }

    bool containsPoint(pair point) { return (point >= UpperLeft && point <= LowerRight); }

    int width() { return LowerRight.x() - UpperLeft.x(); }
    int height() { return LowerRight.y() - UpperLeft.y(); }

    pair upperLeft() { return UpperLeft; }
    pair lowerRight() { return LowerRight; }

protected:
    pair UpperLeft, LowerRight;
};

typedef CRect rect;

class CHelpers
{
public:
    // splits a string into a vector based on a separator
    static void explode(char separator, std::string str, std::vector<std::string>& data)
    {
        size_t pos = str.find_first_of(separator);
        while (pos != std::string::npos)
        {
            if (pos > 0)
                data.push_back(str.substr(0, pos));

            str = str.substr(pos+1);
            pos = str.find_first_of(separator);
        }
        if (str.length() > 0)
            data.push_back(str);
    }

    static char getNextLetter(char currentLetter)
    {
        std::string alphabet("-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+");
        size_t pos = alphabet.find_first_of(currentLetter);
        return alphabet[pos+1];
    }

    static char getPreviousLetter(char currentLetter)
    {
        std::string alphabet("-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+");
        size_t pos = alphabet.find_first_of(currentLetter);
        return alphabet[pos-1];
    }
};

#endif
